package com.hung.trade.pay.service.impl;

import com.alibaba.fastjson.JSON;
import com.hung.trade.common.constants.TradeEnums;
import com.hung.trade.common.exception.PayException;
import com.hung.trade.common.exception.TradeException;
import com.hung.trade.common.protocol.pay.*;
import com.hung.trade.common.rocketmq.RocketMQProducer;
import com.hung.trade.common.utils.IdGenerator;
import com.hung.trade.dao.mapper.TradeMqProducerTempMapper;
import com.hung.trade.dao.mapper.TradePayMapper;
import com.hung.trade.dao.pojo.TradeMqProducerTemp;
import com.hung.trade.dao.pojo.TradeMqProducerTempExample;
import com.hung.trade.dao.pojo.TradePay;
import com.hung.trade.dao.pojo.TradePayExample;
import com.hung.trade.pay.service.IPayService;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author hungki
 * @createTime 2018-10-09 下午 4:30
 */
@Service
public class PayServiceImpl  implements IPayService{
    private static final Logger logger = LoggerFactory.getLogger(PayServiceImpl.class);
    @Autowired
    private TradePayMapper tradePayMapper;
    @Autowired
    private RocketMQProducer rocketMQProducer;
    @Autowired
    private TradeMqProducerTempMapper tradeMqProducerTempMapper;

    // 要和spring里的配置文件的groupName属性的值一致
    private static final String groupName="pay_group_name";

    private ExecutorService executorService = Executors.newFixedThreadPool(10);
    @Override
    @Transactional
    public ChangeUserMoneyResp changeUserMoney(ChangeUserMoneyReq changeUserMoneyReq) {
        ChangeUserMoneyResp resp= new ChangeUserMoneyResp();




        return resp;
    }

    @Override
    @Transactional
    public CreatePaymentResp createPayment(CreatePaymentReq createPaymentReq) {
        CreatePaymentResp resp= new CreatePaymentResp();

        TradePayExample payExample = new TradePayExample();
        payExample.createCriteria().andOrderIdEqualTo(createPaymentReq.getOrderId())
                .andIsPaidEqualTo(TradeEnums.YesNoEnum.YES.getCode());
        List<TradePay> tradePays =  tradePayMapper.selectByExample(payExample);
        if(null!=tradePays && tradePays.size()>=0){
            throw new PayException("订单已经支付");
        }
        String payId = IdGenerator.generatorUUID();
        TradePay pay = new TradePay();
        pay.setOrderId(createPaymentReq.getOrderId());
        pay.setIsPaid(TradeEnums.YesNoEnum.NO.getCode());
        pay.setPayAmount(createPaymentReq.getPayAmount());
        pay.setPayId(payId);

        int i =tradePayMapper.insert(pay);
        if(i<=0){
            throw new PayException("字符信息保存数据库异常");
        }

        return resp;
    }

    @Override
    @Transactional
    public CallbackPaymentResp callbackPayment(CallbackPaymentReq callbackPaymentReq) {
        CallbackPaymentResp resp= new CallbackPaymentResp();

        if(callbackPaymentReq.getIsPaid().equals(TradeEnums.YesNoEnum.YES.getCode())){
            TradePayExample example =new TradePayExample();
            example.createCriteria().andPayIdEqualTo(callbackPaymentReq.getPayId());
            List<TradePay> pays = tradePayMapper.selectByExample(example);
            if(null==pays || pays.size()<=0){
                throw  new PayException("没有找到支付订单");
            }
            final TradePay pay = pays.get(0);
            if(pay.getIsPaid().equals(TradeEnums.YesNoEnum.YES.getCode())){
                throw  new PayException("订单已支付");
            }
            pay.setIsPaid(TradeEnums.YesNoEnum.YES.getCode());

            example =new TradePayExample();
            example.createCriteria().andPayIdEqualTo(callbackPaymentReq.getPayId()).andIsPaidEqualTo(TradeEnums.YesNoEnum.NO.getCode());
            int i =tradePayMapper.updateByExample(pay,example);

            if(i==1){
                //更新成功，说明已经修改了数据库的支付状态为已支付，这个时候分两步，
                // 1、先保存要发送到mq数据到数据库，（由于是保存数据库，所以和上述操作在一个事务中，这样保证了数据一定能插入数据库，mq发送失败后，定时任务可以扫描该表进行更新状态）
                // 2、然后调用线程池发送数据出去，

                //1、 先保存要发送到mq数据到数据库
                final PaidMQ paidMQ = new PaidMQ();
                paidMQ.setPayId(pay.getPayId());
                paidMQ.setPayAmount(pay.getPayAmount());
                paidMQ.setOrderId(pay.getOrderId());

                final TradeMqProducerTemp tradeMqProducerTemp = new TradeMqProducerTemp();
                tradeMqProducerTemp.setGroupName(groupName);
                tradeMqProducerTemp.setCreateTime(new Date());
                tradeMqProducerTemp.setMsgBody(JSON.toJSONString(paidMQ));
                tradeMqProducerTemp.setMsgKeys(pay.getPayId());
                tradeMqProducerTemp.setMsgTag(TradeEnums.OrderTopicAndTagEnum.ORDER_PAID.getTags());
                i =tradeMqProducerTempMapper.insert(tradeMqProducerTemp);
                if(i!=1){
                    throw  new PayException("支付成功后需要创建mq消息先保存到数据库失败");
                }
                //2、调用线程池发送数据
                executorService.submit(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            SendResult sendResult  = rocketMQProducer.sendMsg(TradeEnums.OrderTopicAndTagEnum.ORDER_PAID,tradeMqProducerTemp.getMsgKeys(),tradeMqProducerTemp.getMsgBody());
                            System.out.println("sendResult = " + sendResult);
                            if(sendResult.getSendStatus().equals(SendStatus.SEND_OK)){
                                TradeMqProducerTempExample example = new TradeMqProducerTempExample();
                                example.createCriteria().andGroupNameEqualTo(groupName)
                                        .andMsgTagEqualTo(tradeMqProducerTemp.getMsgTag())
                                        .andMsgKeysEqualTo(tradeMqProducerTemp.getMsgKeys());

                                int i =tradeMqProducerTempMapper.deleteByExample(example);
                                if(i==1){
                                    logger.debug("消息发送成功，删除数据库mq消息的记录-成功");
                                }else{
                                    logger.error("消息发送成功，删除数据库mq消息的记录-失败");
                                }
                            }
                        } catch (TradeException e) {
                            e.printStackTrace();
                        }
                    }
                });

            }


        }else{

            //支付失败，do nothing!
        }


        return resp;
    }
}
